local Piece = require "packages.chess-games.xiangqi.core.piece"

---@class Xiangqi.Engine : Base.Engine
---@field public pieces table<integer, Xiangqi.Piece>
local Engine = Fk.Base.Engine:subclass("Xiangqi.Engine")

-- 全是写死棋子坐标和id的，过于繁冗，折叠起来
do -- Please give me a piece of pie.
  -- 红方
  Engine.rR1 =  1
  Engine.rN1 =  2
  Engine.rB1 =  3
  Engine.rA1 =  4
  Engine.rK  =  5
  Engine.rA2 =  6
  Engine.rB2 =  7
  Engine.rN2 =  8
  Engine.rR2 =  9
  Engine.rC1 = 10
  Engine.rC2 = 11
  Engine.rP1 = 12
  Engine.rP2 = 13
  Engine.rP3 = 14
  Engine.rP4 = 15
  Engine.rP5 = 16

  -- 黑方
  Engine.bR1 = -1
  Engine.bN1 = -2
  Engine.bB1 = -3
  Engine.bA1 = -4
  Engine.bK  = -5
  Engine.bA2 = -6
  Engine.bB2 = -7
  Engine.bN2 = -8
  Engine.bR2 = -9
  Engine.bC1 = -10
  Engine.bC2 = -11
  Engine.bP1 = -12
  Engine.bP2 = -13
  Engine.bP3 = -14
  Engine.bP4 = -15
  Engine.bP5 = -16

  -- Engine 内部记录每颗棋子的初始坐标
  Engine.initialPositions = {
    -- 红方
    [Engine.rR1] = {x=1, y=10},
    [Engine.rN1] = {x=2, y=10},
    [Engine.rB1] = {x=3, y=10},
    [Engine.rA1] = {x=4, y=10},
    [Engine.rK ] = {x=5, y=10},
    [Engine.rA2] = {x=6, y=10},
    [Engine.rB2] = {x=7, y=10},
    [Engine.rN2] = {x=8, y=10},
    [Engine.rR2] = {x=9, y=10},
    [Engine.rC1] = {x=2, y=8},
    [Engine.rC2] = {x=8, y=8},
    [Engine.rP1] = {x=1, y=7},
    [Engine.rP2] = {x=3, y=7},
    [Engine.rP3] = {x=5, y=7},
    [Engine.rP4] = {x=7, y=7},
    [Engine.rP5] = {x=9, y=7},

    -- 黑方
    [Engine.bR1] = {x=1, y=1},
    [Engine.bN1] = {x=2, y=1},
    [Engine.bB1] = {x=3, y=1},
    [Engine.bA1] = {x=4, y=1},
    [Engine.bK ] = {x=5, y=1},
    [Engine.bA2] = {x=6, y=1},
    [Engine.bB2] = {x=7, y=1},
    [Engine.bN2] = {x=8, y=1},
    [Engine.bR2] = {x=9, y=1},
    [Engine.bC1] = {x=2, y=3},
    [Engine.bC2] = {x=8, y=3},
    [Engine.bP1] = {x=1, y=4},
    [Engine.bP2] = {x=3, y=4},
    [Engine.bP3] = {x=5, y=4},
    [Engine.bP4] = {x=7, y=4},
    [Engine.bP5] = {x=9, y=4},
  }

  Engine.ChineseNumbers = {"一", "二", "三", "四", "五", "六", "七", "八", "九"}
  Engine.ArabicNumbers = {"１", "２", "３", "４", "５", "６", "７", "８", "９"}
end

function Engine:initialize()
  Fk.Base.Engine.initialize(self)

  self.pieces = {}
end

function Engine:addPiece(piece)
  self.pieces[piece.id] = piece
end

---@param id integer
---@return Xiangqi.Piece
function Engine:getPieceById(id)
  return self.pieces[id]
end

---@return integer[][]
function Engine:createBoard()
  -- 创建空棋盘
  local board = {
    {0, 0, 0, 0, 0, 0, 0, 0, 0},
    {0, 0, 0, 0, 0, 0, 0, 0, 0},
    {0, 0, 0, 0, 0, 0, 0, 0, 0},
    {0, 0, 0, 0, 0, 0, 0, 0, 0},
    {0, 0, 0, 0, 0, 0, 0, 0, 0},
    -- ↑黑方 楚河汉界 红方↓
    {0, 0, 0, 0, 0, 0, 0, 0, 0},
    {0, 0, 0, 0, 0, 0, 0, 0, 0},
    {0, 0, 0, 0, 0, 0, 0, 0, 0},
    {0, 0, 0, 0, 0, 0, 0, 0, 0},
    {0, 0, 0, 0, 0, 0, 0, 0, 0},
  }

  -- 遍历32颗棋子，根据 initialPositions 写回初始坐标
  for id, pos in pairs(self.initialPositions) do
    board[pos.y][pos.x] = id
  end

  return board
end

function Engine:getLineNumber(x, color)
  if color == "red" then
    return self.ChineseNumbers[10 - x]
  else
    return self.ArabicNumbers[x]
  end
end

function Engine:translateMovement(pieceId, board, fromX, fromY, x, y)
  local piece = self:getPieceById(pieceId)
  local color = piece:getColor()

  local pieceName = ('<font color="%s">%s</font>'):format(color, color == "red" and piece.redStr or piece.blackStr)
  local fromLine = self:getLineNumber(fromX, color)

  -- 判这列是否还有自己的
  for _y = 1, 10 do
    if _y ~= fromY then
      local p = self:getPieceById(board[_y][fromX])
      if p and p.name == piece.name and p:getColor() == color then
        -- 若在自己前进方向发现有其他棋子则。。
        if (color == "red" and _y < fromY) or
          (color == "black" and _y > fromY) then
          pieceName = "后" .. pieceName
        else
          pieceName = "前" .. pieceName
        end

        fromLine = ""
        break
      end
    end
  end

  -- 判断移动方向
  local direction, target
  if fromY == y then -- 横向移动
    direction = "平"
    target = self:getLineNumber(x, color)
  else
    if (color == "red" and y < fromY) or
      (color == "black" and y > fromY) then
      direction = "进"
    else
      direction = "退"
    end

    if piece.name == "knight" or
      piece.name == "advisor" or
      piece.name == "bishop" then
      target = self:getLineNumber(x, color)
    else
      if color == "red" then
        target = self.ChineseNumbers[math.abs(y - fromY)]
      else
        target = self.ArabicNumbers[math.abs(y - fromY)]
      end
    end
  end

  return pieceName .. fromLine .. direction .. target
end

function Engine:isChecking(board, color)
  for Y, arrX in ipairs(board) do
    for X, id in ipairs(arrX) do
      if (id > 0 and color == "red") or (id < 0 and color == "black") then
        local kingId = id > 0 and self.bK or self.rK
        local kingX, kingY
        for _y, xArr in ipairs(board) do
          for _x, _id in ipairs(xArr) do
            if _id == kingId then
              kingX = _x
              kingY = _y
              break
            end
          end
          if kingX then break end
        end
        if self:getPieceById(id):canMoveTo(board, X, Y, kingX, kingY) then
          return true
        end
      end
    end
  end
end

return Engine
